<!DOCTYPE html>
<html>
<head>
    <title>绚丽烟花2025</title>
    <style>
        body {
            margin: 0;
            overflow: hidden;
            background: #000;
        }
        canvas {
            display: block;
        }
    </style>
</head>
<body>
    <canvas id="canvas"></canvas>
    <script>
        // JavaScript代码




        bj_fill_alpha=0.3;// 越小值填充透明度越少偏白
        px_die_alpha=0.1; // 值越小过滤越慢消失
        px_die_r=1000; // 越小值越快消亡半径可以负数
        px_num=10;//越小值越小点数
        px_update_alpha=0.001;// 越小值越慢消失
        px_space=1;// 越小值越慢
        auto_sun= 0.69;// 值越大自动烟花空屏率越大




const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;

let fireworks = [];
let particles = [];

// 随机数生成函数
function random(min, max) {
    return Math.random() * (max - min) + min;
}

// 粒子类
class Particle {
    constructor(x, y, hue, size, angle, speed, shape) {
        this.x = x;
        this.y = y;
        this.hue = hue;
        this.size = size;
        this.angle = angle;
        this.speed = speed;
        this.shape = shape;
        this.alpha = 1;
    }

    update() {
        this.x += Math.cos(this.angle) * this.speed;
        this.y += Math.sin(this.angle) * this.speed;
        this.alpha -= px_update_alpha;
        return this.alpha <= 0;
    }

    draw() {
        ctx.save();
        ctx.globalAlpha = this.alpha;
        ctx.beginPath();
        if (this.shape === 'circle') {
            ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
        } else if (this.shape === 'heart') {
            // 心形路径
            ctx.moveTo(this.x, this.y);
            ctx.bezierCurveTo(this.x + this.size, this.y - this.size, this.x + this.size, this.y - this.size * 2, this.x, this.y - this.size * 2);
            ctx.bezierCurveTo(this.x - this.size, this.y - this.size * 2, this.x - this.size, this.y - this.size, this.x, this.y);
        } else if (this.shape === 'spiral') {
            // 螺旋路径
            ctx.arc(this.x, this.y, this.size * 2, 0, Math.PI * 2);
        } else {
            ctx.rect(this.x, this.y, this.size, this.size);
        }
        ctx.fillStyle = `hsla(${this.hue}, 100%, 50%, ${this.alpha})`;
        ctx.fill();
        ctx.restore();
    }
}

// 烟花类
class Firework {
    constructor(x, y, targetX, targetY, color, size) {
        this.x = x;
        this.y = y;
        this.startX = x;
        this.startY = y;
        this.targetX = targetX;
        this.targetY = targetY;
        this.color = color;
        this.size = size;
        this.distance = Math.sqrt(Math.pow(targetX - x, 2) + Math.pow(targetY - y, 2));
        this.angle = Math.atan2(targetY - y, targetX - x);
        this.speed = px_space;
        this.acceleration = 1.05;
        this.brightness = random(50, 80);
        this.targetRadius = 1;
        this.trail = [];
        this.trailLength = 10;
    }

    update() {
        this.trail.push([this.x, this.y]);
        if (this.trail.length > this.trailLength) {
            this.trail.shift();
        }

        this.speed *= this.acceleration;

        let vx = Math.cos(this.angle) * this.speed;
        let vy = Math.sin(this.angle) * this.speed;

        this.distanceTraveled = Math.sqrt(Math.pow(this.x - this.startX, 2) + Math.pow(this.y - this.startY, 2));
        // console.log(this.distanceTraveled,">",this.distance);//半径>=指定值时就true消亡 splice
        if (this.distanceTraveled >= this.distance+px_die_r) {
            createParticles(this.targetX, this.targetY, this.color, this.size);
            return true;
        }

        this.x += vx;
        this.y += vy;
        return false;
    }

    draw() {
        ctx.beginPath();
        ctx.moveTo(this.trail[0][0], this.trail[0][1]);
        for (let i = 1; i < this.trail.length; i++) {
            ctx.lineTo(this.trail[i][0], this.trail[i][1]);
        }
        ctx.strokeStyle = `hsla(${this.color}, 100%, ${this.brightness}%, ${this.brightness / 100})`;
        ctx.lineWidth = this.targetRadius * 2;
        ctx.stroke();
    }
}

// 创建粒子
function createParticles(x, y, hue, size) {
    const shapes = ['circle', 'heart', 'spiral', 'random'];
    const selectedShape = shapes[Math.floor(random(0, shapes.length))];
    let particleCount = Math.floor(random(1, 20) * size);

    for (let i = 0; i < particleCount; i++) {
        const angle = (Math.PI * 2 * i) / particleCount;
        const speed = random(0.01, 1) * size;
        particles.push(new Particle(x, y, hue, size, angle, speed, selectedShape));
    }
}

// 自动发射烟花
function autoLaunchFirework() {
    const x = random(0, canvas.width);
    const y = canvas.height;
    const targetX = random(0, canvas.width);
    const targetY = random(0, canvas.height * 0.3);
    const color = random(0, 360);
    const size = random(1, 3);
    fireworks.push(new Firework(x, y, targetX, targetY, color, size));
}

// 动画循环
function animate() {
    requestAnimationFrame(animate);
    ctx.fillStyle = 'rgba(0, 0, 0, bj_fill_alpha)';
    ctx.fillRect(0, 0, canvas.width, canvas.height);

    if (random(0, 1) > auto_sun) {
        autoLaunchFirework();
    }

    for (let i = fireworks.length - 1; i >= 0; i--) {
        if (fireworks[i].update()) {
            fireworks.splice(i, 1);
        } else {
            fireworks[i].draw();
        }
    }

    for (let i = particles.length - 1; i >= 0; i--) {
        if (particles[i].update()) {
            particles.splice(i, 1);
        } else {
            particles[i].draw();
        }
    }
}

animate();

// 用户交互
canvas.addEventListener('click', (e) => {
    const x = e.clientX;
    const y = e.clientY;
    createParticles(x, y, random(0, 360), random(1, 3));
});

</script>
</body>
</html>

